
package com.probiz.estore.customer.dao.impl;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import com.probiz.estore.common.helper.ConfigUtil;
import com.probiz.estore.common.model.customer.Customer;
import com.probiz.estore.common.model.customer.Customer.FilterHqlName;
import com.probiz.estore.common.model.other.Tag;
import com.probiz.estore.common.model.system.AppUser;
import com.probiz.estore.common.model.system.Region;
import com.probiz.estore.common.util.DateUtil;
import com.probiz.estore.core.model.BaseObject;
import com.probiz.estore.core.search.SearchCriteria;
import com.probiz.estore.core.util.StringUtil;
import com.probiz.estore.customer.dao.CustomerDao;
import com.probiz.estore.customer.model.CustomerSearchCriteria;
import com.probiz.estore.system.dao.RegionDao;
import com.probiz.estore.system.dao.impl.AppUserDaoImpl;

/**
 * Customer Data Access Object (DAO) implementation. Developer introduced
 * interfaces should be declared here. Won't get overwritten.
 */
public class CustomerDaoImpl extends AppUserDaoImpl<Customer> implements CustomerDao {
	private RegionDao regionDao;
	

	public void setRegionDao(RegionDao regionDao) {
		this.regionDao = regionDao;
	}

	/**
	 * 标准参考写法
	 * 
	 * @since V3.5
	 */
	@Override
	protected void initFilterHqlMap() {
		filterHqlMap.put(BaseObject.FilterHqlName.DEFAULT, "from Customer c where c.deleted=0 and c.appuserId!=-2");
		filterHqlMap.put(FilterHqlName.COUNT_BY_MEMBERSHIP_ID, "select count(*) from Customer c where c.membership.membershipId=? and c.deleted=0");
		filterHqlMap.put(FilterHqlName.COUNT_CUSTOMER_TOTAL, "select count(*) from Customer c where c.deleted=0 and c.appuserId!=-2");
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.customer.dao.CustomerDao#searchByCriteria(com.probiz.estore.customer.model.CustomerSearchCriteria, com.probiz.estore.core.search.SearchCriteria)
	 */
	public List<Customer> searchByCriteria(CustomerSearchCriteria customerSearchCriteria, SearchCriteria searchCriteria){
		 //-begin:获得所有符合的标签id
    	Set<Integer> tagIdSet = new HashSet<Integer>();
        if (StringUtils.isNotBlank(customerSearchCriteria.getTags())) {
        	String[] tagNameArray = customerSearchCriteria.getTags().trim().replaceAll("\\s+",",").split(",");
        	for(int i=0; i< tagNameArray.length; i++){
        		tagIdSet.addAll(this.findByHql("select t.tagId from Tag t where t.tagName like ? and t.module=?", "%"+tagNameArray[i]+"%",Tag.MODULE_CUSTOMER));
        	}
        }
        //-end:获得所有符合的标签id
        
		StringBuffer hqlsb = new StringBuffer(100);
        List<Object> paramList = new ArrayList<Object>();
        //start:构建HQL语句
        hqlsb.append("from Customer c where c.deleted=0 and c.appuserId!=-2 ");
        //-start：一般域
        if(StringUtils.isNotBlank(customerSearchCriteria.getFieldValue())){
        	hqlsb.append(" and c.").append(customerSearchCriteria.getFieldName()).append(" like ?");
        	paramList.add("%"+customerSearchCriteria.getFieldValue().trim()+"%");
        }
        //-end: 一般域
        
      //-begin:会员等级
        if (!ArrayUtils.isEmpty(customerSearchCriteria.getMembershipIds())) {
        	String membershipIdsString = StringUtil.arrayToString(customerSearchCriteria.getMembershipIds(),",");
        	if(StringUtils.isNotEmpty(membershipIdsString)){
		    	hqlsb.append(" and (");
		    	hqlsb.append("c.membership.membershipId in (").append(membershipIdsString).append(")");
		    	hqlsb.append(" )");
        	}
        }
        if(null != customerSearchCriteria.getMembershipId()){
        	hqlsb.append(" and c.membership.membershipId = ? ");
        	paramList.add(customerSearchCriteria.getMembershipId());
        }
        //-end:会员等级
        //-start:最低积分
        if (null != customerSearchCriteria.getLowestShopPoint()) {
            hqlsb.append(" and c.shopPoint.total >= ?");
            paramList.add(customerSearchCriteria.getLowestShopPoint());
        }
        //-end:最低积分
        //-start:最高积分
        if (null != customerSearchCriteria.getHighestShopPoint()) {
            hqlsb.append(" and c.shopPoint.total <= ?");
            paramList.add(customerSearchCriteria.getHighestShopPoint());
        }
        //-end:最高积分
        //-start:注册开始时间
        if(StringUtils.isNotBlank(customerSearchCriteria.getStartCreateTime())){
			try {
				Date date = DateUtil.convertStringToDate(ConfigUtil.getInstance().getDatePattern(),customerSearchCriteria.getStartCreateTime());
				Calendar calender = Calendar.getInstance();
				calender.setTime(date);
				calender.set(Calendar.HOUR_OF_DAY, 0);
				calender.set(Calendar.MINUTE, 0);
				calender.set(Calendar.SECOND, 0);
				hqlsb.append(" and c.createTime >= ?");
				paramList.add(calender.getTime());
			} catch (ParseException e) {
				e.printStackTrace();
			}
        }
        //-end:注册开始时间
        //-start:注册结束时间
        if(StringUtils.isNotBlank(customerSearchCriteria.getEndCreateTime())){
			try {
				Date date = DateUtil.convertStringToDate(ConfigUtil.getInstance().getDatePattern(),customerSearchCriteria.getEndCreateTime());
				Calendar calender = Calendar.getInstance();
				calender.setTime(date);
				calender.add(Calendar.DAY_OF_YEAR, 1);
				calender.set(Calendar.HOUR_OF_DAY, 0);
				calender.set(Calendar.MINUTE, 0);
				calender.set(Calendar.SECOND, 0);
				hqlsb.append(" and c.createTime <= ?");
				paramList.add(calender.getTime());
			} catch (ParseException e) {
				e.printStackTrace();
			}
        }
        //-end:注册结束时间
        //-start:地域地理位置
        if(StringUtils.isNotBlank(customerSearchCriteria.getRegionId())){
        	Region region = regionDao.getById(Integer.valueOf(customerSearchCriteria.getRegionId()));
        	if(null != region){
        		String[] regionKeys = region.getFullName().split(",");
        		for(int i=1;i<regionKeys.length;i++){
        			//序号从1开始，不包含“中国”字样
        			hqlsb.append(" and c.address like ?");
        			paramList.add("%"+regionKeys[i]+"%");
        		}
        	}
        }
        //-end:地域地理位置
        //-start:性别
        if(null!=customerSearchCriteria.getGender()){
        	hqlsb.append(" and c.gender = ?");
        	paramList.add(customerSearchCriteria.getGender());
        }
        //-end:性别
        //-start:状态
        if (null != customerSearchCriteria.getStatus()) {
            hqlsb.append(" and c.status = ?");
            paramList.add(customerSearchCriteria.getStatus());
        }
        //-end:状态
        //-begin:标签名称
        if (StringUtils.isNotBlank(customerSearchCriteria.getTags())) {
        	hqlsb.append(" and (");
        	hqlsb.append(" 1=0 ");
        	for(Integer tagId: tagIdSet){
        		hqlsb.append(" or  ','||c.tags||',' like ?");
        		paramList.add("%,"+tagId+",%");
        	}
        	hqlsb.append(" )");
        	
        }
        //-end:标签名称
        //start:order by
        if (null != customerSearchCriteria.getOrderby()) {
            hqlsb.append(" order by ").append(getSortByString(customerSearchCriteria.getOrderby()));
        }else{
        	hqlsb.append(" order by c.createTime desc");
        }
        //end:order by
        
        
        //end:构建HQL语句
        searchCriteria.setHql(hqlsb.toString());
        searchCriteria.removeParamValues();
        for (Object object : paramList) {
           searchCriteria.addParamValue(object);
        }
        List<Customer> list =  searchByCriteria(searchCriteria);
        return list;
	}
	
	 /**
     * 根据orderby获得 hql语句
     *
     * @param orderby 排序id
     * @return hql语句
     */
    private String getSortByString(short orderby) {
        String orderByString;
        switch (orderby) {
        	 case 1:
                 orderByString = "c.createTime asc";
                 break;
             case 2:
                 orderByString = "c.createTime desc";
                 break;
             case 3:
                 orderByString = "convert_gbk(c.firstname) asc";
                 break;
             case 4:
                 orderByString = "convert_gbk(c.firstname) desc";
                 break;
             case 5:
                 orderByString = "c.shopPoint.total asc";
                 break;
             case 6:
                 orderByString = "c.shopPoint.total desc";
                 break;
             case 7:
                 orderByString = "convert_gbk(c.username) asc";
                 break;
             case 8:
                 orderByString = "convert_gbk(c.username) desc";
                 break;
             case 9:
            	 orderByString = "c.email asc";
            	 break;
             case 10:
            	 orderByString = "c.email desc";
            	 break;
             case 11:
            	 orderByString = "c.status desc";
            	 break;
             case 12:
            	 orderByString = "c.status asc";
            	 break;
             default:
                 orderByString = "c.createTime desc";
                 break;
        }
        return orderByString;
    }
	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.customer.dao.CustomerDao#getByAppUserId(java.lang.Integer)
	 */
	public Customer getByAppUserId(Integer appUserId){
		return this.getUniqueByProperty("appuserId", appUserId);
	}

	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.customer.dao.CustomerDao#saveCustomerPreferredLanguage(java.lang.Integer, java.lang.String)
	 */
	public void saveCustomerPreferredLanguage(Integer customerId, String preferLanguage) {
		Customer customer = getByAppUserId(customerId);
		customer.setPreferredLanguage(preferLanguage);
		save(customer);
	}

	/*
	 * (non-Javadoc)
	 * @see com.probiz.estore.customer.dao.CustomerDao#findExportCustomer(java.util.Date)
	 */
	public List<Customer> findExportCustomer(Date lastExecuteTime) {
		String hql="from Customer c";
		if(lastExecuteTime!=null){
			hql=hql+" where c.updateTime>=?";
			return findByHql(hql, lastExecuteTime);			
		}else{
			return findByHql(hql);
		}
	
	}

	public List<String> searchCustomerEmails(int pageNo, int pageSize, List<String> newsletterGroupIds) {
		StringBuilder hql = new StringBuilder("select distinct c.email from Customer c where c.appuserId!=? and c.userType=? and c.isLocked=? and deleted=? order by c.updateTime desc");
		SearchCriteria sc = SearchCriteria.getHqlPagingInstance(hql.toString(), new Object[]{-2, AppUser.USER_TYPE_CUSTOMER, AppUser.CONST_UNLOCKED, AppUser.CONST_UNDELETED}, pageNo, pageSize, null);
		return this.searchByCriteria(sc);
	}
	
	public List<Customer> getListByDeleted() {
		String hql = "from Customer c where c.deleted=0 and c.appuserId!=-2 and c.userType = 0";
		return this.findByHql(hql);
	}
}